﻿//-----------------------------------------------------------------------
// <copyright file="Settings.cs" company="Microsoft Corporation">
//     Copyright Microsoft Corporation. All Rights Reserved. This code released under the terms of the Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.) This is sample code only, do not use in production environments.
// </copyright>
//-----------------------------------------------------------------------
namespace vsarFlightPlan.ViewModels
{
    using System;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Linq;
    using System.Windows.Input;
    using Utilities;
    using VisualStudioOnlineOData;
    using VisualStudioOnlineOData.Models;
    using Windows.Storage;
    using Windows.UI.Popups;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;

    /// <summary>
    ///
    /// </summary>
    internal class Settings : ViewModelBase
    {
        private string _account;
        private bool _fileterLandedProjectsByCount = false;
        private bool _loadingProjects;
        private bool _loadingQueries;
        private string _password;
        private Project _selectedProject;
        private Query _selectedQuery;
        private bool _showByDefaultCancelled;
        private bool _showByDefaultDelayed;
        private bool _showByDefaultIdea;
        private bool _showByDefaultInFlight;
        private bool _showByDefaultLanded;
        private bool _storePassword;
        private int _totalDaysOfLandedProjectsToShow = 30;
        private int _totalLandedProjectsToShow = 3;
        private string _username;
        private ApplicationDataContainer settingsContainer;

        /// <summary>
        /// Initializes a new instance of the <see cref="Settings"/> class.
        /// </summary>
        public Settings()
        {
            Queries = new ObservableCollection<Query>();
            Projects = new ObservableCollection<Project>();
            this.settingsContainer = SettingUtils.SettingsContainer(true);
            if (settingsContainer != null)
            {
                Username = settingsContainer.Read<string>("username", null);
                StorePassword = settingsContainer.Read("storePassword", true);
                Account = settingsContainer.Read<string>("account", null);
                Password = settingsContainer.Read<string>("password", null);
                var projectId = settingsContainer.Read<string>("projectId", null);
                var queryId = settingsContainer.Read<string>("queryId", null);
                ShowByDefaultCancelled = settingsContainer.Read("ShowByDefaultCancelled", true);
                ShowByDefaultDelayed = settingsContainer.Read("ShowByDefaultDelayed", true);
                ShowByDefaultIdea = settingsContainer.Read("ShowByDefaultIdea", true);
                ShowByDefaultInFlight = settingsContainer.Read("ShowByDefaultInFlight", true);
                ShowByDefaultLanded = settingsContainer.Read("ShowByDefaultLanded", true);
                FilterLandedProjectsByCount = settingsContainer.Read("FilterLandedProjectsByCount", false);
                TotalLandedProjectsToShow = settingsContainer.Read("TotalLandedProjectsToShow", 3);
                TotalDaysOfLandedProjectsToShow = settingsContainer.Read("TotalDaysOfLandedProjectsToShow", 30);
                LoadProjectList(projectId, queryId);
            }

            RefreshProjects = new Command(() =>
                {
                    if (SelectedProject != null)
                    {
                        if (SelectedQuery != null)
                        {
                            LoadProjectList(SelectedProject.Id, SelectedQuery.QueryId);
                        }
                        else
                        {
                            LoadProjectList(SelectedProject.Id);
                        }
                    }
                    else
                    {
                        LoadProjectList();
                    }
                });

            RefreshQueries = new Command(() =>
                {
                    if (SelectedQuery != null)
                    {
                        LoadQueryList(SelectedQuery.QueryId);
                    }
                    else
                    {
                        LoadQueryList();
                    }
                });
            GoBack = new Command(() =>
                {
                    UpdateSettings();
                    (Window.Current.Content as Frame).GoBack();
                });

            ClearLocalCache = new Command(async () =>
                {
                    try
                    {
                        var file = await ApplicationData.Current.LocalFolder.GetFileAsync("workItems");
                        await file.DeleteAsync(StorageDeleteOption.PermanentDelete);
                    }
                    catch (FileNotFoundException) { }
                    await new MessageDialog("Cache has been cleared").ShowAsync();
                });
        }

        /// <summary>
        /// Gets or sets the account.
        /// </summary>
        /// <value>
        /// The account.
        /// </value>
        public string Account
        {
            get
            {
                return _account;
            }
            set
            {
                this.UpdateProperty(ref _account, value);
            }
        }

        /// <summary>
        /// Gets or sets the clear local cache.
        /// </summary>
        /// <value>
        /// The clear local cache.
        /// </value>
        public ICommand ClearLocalCache { get; set; }

        public bool FilterLandedProjectsByCount
        {
            get
            {
                return _fileterLandedProjectsByCount;
            }
            set
            {
                this.UpdateProperty(ref _fileterLandedProjectsByCount, value);
            }
        }

        /// <summary>
        /// Gets or sets the go back.
        /// </summary>
        /// <value>
        /// The go back.
        /// </value>
        public ICommand GoBack { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether [loading projects].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [loading projects]; otherwise, <c>false</c>.
        /// </value>
        public bool LoadingProjects
        {
            get
            {
                return _loadingProjects;
            }
            set
            {
                this.UpdateProperty(ref _loadingProjects, value);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [loading queries].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [loading queries]; otherwise, <c>false</c>.
        /// </value>
        public bool LoadingQueries
        {
            get
            {
                return _loadingQueries;
            }
            set
            {
                this.UpdateProperty(ref _loadingQueries, value);
            }
        }

        /// <summary>
        /// Gets or sets the password.
        /// </summary>
        /// <value>
        /// The password.
        /// </value>
        public string Password
        {
            get
            {
                return _password;
            }
            set
            {
                this.UpdateProperty(ref _password, value);
            }
        }

        /// <summary>
        /// Gets or sets the projects.
        /// </summary>
        /// <value>
        /// The projects.
        /// </value>
        public ObservableCollection<Project> Projects { get; set; }

        /// <summary>
        /// Gets or sets the queries.
        /// </summary>
        /// <value>
        /// The queries.
        /// </value>
        public ObservableCollection<Query> Queries { get; set; }

        /// <summary>
        /// Gets or sets the refresh projects.
        /// </summary>
        /// <value>
        /// The refresh projects.
        /// </value>
        public ICommand RefreshProjects { get; set; }

        /// <summary>
        /// Gets or sets the refresh queries.
        /// </summary>
        /// <value>
        /// The refresh queries.
        /// </value>
        public ICommand RefreshQueries { get; set; }

        /// <summary>
        /// Gets or sets the selected project.
        /// </summary>
        /// <value>
        /// The selected project.
        /// </value>
        public Project SelectedProject
        {
            get
            {
                return _selectedProject;
            }
            set
            {
                this.UpdateProperty(ref _selectedProject, value);
            }
        }

        /// <summary>
        /// Gets or sets the selected query.
        /// </summary>
        /// <value>
        /// The selected query.
        /// </value>
        public Query SelectedQuery
        {
            get
            {
                return _selectedQuery;
            }
            set
            {
                this.UpdateProperty(ref _selectedQuery, value);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [show by default cancelled].
        /// </summary>
        /// <value>
        /// <c>true</c> if [show by default cancelled]; otherwise, <c>false</c>.
        /// </value>
        public bool ShowByDefaultCancelled
        {
            get
            {
                return _showByDefaultCancelled;
            }
            set
            {
                this.UpdateProperty(ref _showByDefaultCancelled, value);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [show by default delayed].
        /// </summary>
        /// <value>
        /// <c>true</c> if [show by default delayed]; otherwise, <c>false</c>.
        /// </value>
        public bool ShowByDefaultDelayed
        {
            get
            {
                return _showByDefaultDelayed;
            }
            set
            {
                this.UpdateProperty(ref _showByDefaultDelayed, value);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [show by default idea].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [show by default idea]; otherwise, <c>false</c>.
        /// </value>
        public bool ShowByDefaultIdea
        {
            get
            {
                return _showByDefaultIdea;
            }
            set
            {
                this.UpdateProperty(ref _showByDefaultIdea, value);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [show by default in flight].
        /// </summary>
        /// <value>
        /// <c>true</c> if [show by default in flight]; otherwise, <c>false</c>.
        /// </value>
        public bool ShowByDefaultInFlight
        {
            get
            {
                return _showByDefaultInFlight;
            }
            set
            {
                this.UpdateProperty(ref _showByDefaultInFlight, value);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [show by default landed].
        /// </summary>
        /// <value>
        /// <c>true</c> if [show by default landed]; otherwise, <c>false</c>.
        /// </value>
        public bool ShowByDefaultLanded
        {
            get
            {
                return _showByDefaultLanded;
            }
            set
            {
                this.UpdateProperty(ref _showByDefaultLanded, value);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [store password].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [store password]; otherwise, <c>false</c>.
        /// </value>
        public bool StorePassword
        {
            get
            {
                return _storePassword;
            }
            set
            {
                this.UpdateProperty(ref _storePassword, value);
            }
        }

        public int TotalDaysOfLandedProjectsToShow
        {
            get
            {
                return _totalDaysOfLandedProjectsToShow;
            }
            set
            {
                this.UpdateProperty(ref _totalDaysOfLandedProjectsToShow, value);
            }
        }

        public int TotalLandedProjectsToShow
        {
            get
            {
                return _totalLandedProjectsToShow;
            }
            set
            {
                this.UpdateProperty(ref _totalLandedProjectsToShow, value);
            }
        }

        /// <summary>
        /// Gets or sets the username.
        /// </summary>
        /// <value>
        /// The username.
        /// </value>
        public string Username
        {
            get
            {
                return _username;
            }
            set
            {
                this.UpdateProperty(ref _username, value);
            }
        }

        public bool UpdateSettings()
        {
            settingsContainer.Values["account"] = Account;
            settingsContainer.Values["username"] = Username;
            settingsContainer.Values["projectId"] = SelectedProject != null ? SelectedProject.Id : null;
            settingsContainer.Values["queryId"] = SelectedQuery != null ? SelectedQuery.QueryId : null;
            settingsContainer.Values["storePassword"] = StorePassword;
            settingsContainer.Values["ShowByDefaultCancelled"] = ShowByDefaultCancelled;
            settingsContainer.Values["ShowByDefaultDelayed"] = ShowByDefaultDelayed;
            settingsContainer.Values["ShowByDefaultIdea"] = ShowByDefaultIdea;
            settingsContainer.Values["ShowByDefaultInFlight"] = ShowByDefaultInFlight;
            settingsContainer.Values["ShowByDefaultLanded"] = ShowByDefaultLanded;
            settingsContainer.Values["FilterLandedProjectsByCount"] = FilterLandedProjectsByCount;
            settingsContainer.Values["TotalLandedProjectsToShow"] = TotalLandedProjectsToShow;
            settingsContainer.Values["TotalDaysOfLandedProjectsToShow"] = TotalDaysOfLandedProjectsToShow;
            if (StorePassword)
            {
                settingsContainer.Values["password"] = Password;
            }
            else
            {
                settingsContainer.Values["password"] = null;
            }

            return !string.IsNullOrWhiteSpace(Account) &&
                   !string.IsNullOrWhiteSpace(Username) &&
                   SelectedProject != null &&
                   SelectedQuery != null;
        }

#if TABLET
#endif

        /// <summary>
        /// Gets the credentials.
        /// </summary>
        /// <returns></returns>
        private Credentials GetCredentials()
        {
            if (string.IsNullOrWhiteSpace(Account) || string.IsNullOrWhiteSpace(Username) || string.IsNullOrWhiteSpace(Password))
            {
                return null;
            }

            return new Credentials(Account, Username, Password);
        }

        /// <summary>
        /// Loads the project list.
        /// </summary>
        /// <param name="selectProjectId">The select project identifier.</param>
        /// <param name="selectedQueryId">The selected query identifier.</param>
        private async void LoadProjectList(string selectProjectId = null, string selectedQueryId = null)
        {
            var credentials = GetCredentials();
            if (credentials == null)
            {
                return;
            }

            LoadingProjects = true;

            var projects = await VisualStudioOnlineOData.Projects.GetProjectsAsync(credentials);
            if (projects == null)
            {
                LoadingProjects = false;
                return;
            }

            foreach (var project in projects.OrderBy(o => o.Title))
            {
                if (!Projects.Any(_ => _.Id == project.Id))
                {
                    Projects.Add(project);
                }
            }

            if (selectProjectId != null)
            {
                var project = Projects.FirstOrDefault(_ => _.Id == selectProjectId);
                if (project != null)
                {
                    SelectedProject = project;
                }
            }
            else
            {
                if (Projects.Any())
                {
                    SelectedProject = Projects.First();
                }
            }

            LoadingProjects = false;
            LoadQueryList(selectedQueryId);
        }

        /// <summary>
        /// Loads the query list.
        /// </summary>
        /// <param name="selectedQueryId">The selected query identifier.</param>
        private async void LoadQueryList(string selectedQueryId = null)
        {
            var credentials = GetCredentials();
            if (credentials == null)
            {
                return;
            }

            LoadingQueries = true;
            var queries = await VisualStudioOnlineOData.Queries.GetQueriesAsync(credentials);
            Queries.Clear();
            if (queries == null)
            {
                LoadingQueries = false;
                return;
            }

            foreach (var query in queries.Where(o => string.Compare(o.Project, SelectedProject.Title) == 0).OrderBy(o => o.Name))
            {
                if (!Queries.Any(_ => _.QueryId == query.QueryId))
                {
                    Queries.Add(query);
                }
            }

            if (!Queries.Any())
            {
                if (selectedQueryId != null)
                {
                    var query = Queries.FirstOrDefault(_ => _.QueryId == selectedQueryId);
                    if (query != null)
                    {
                        SelectedQuery = query;
                    }
                }
                else
                {
                    SelectedQuery = Queries.First();
                }
            }

            LoadingQueries = false;
        }
    }
}